; ==============================================================================
; Apple II [$D0 ROM] (341-0016) - Programmer's Aid #1 [1978]
; ------------------------------------------------------------------------------
; Part 3 [$D4D5~$D52D]: 6502 Relocation Subroutine
; by Steve Wozniak [WOZ], 1977-11-10;
; Copyright (c) 1978 by Apple Computer Inc. All Rights Reserved
; ------------------------------------------------------------------------------
; Instructions are in the Programmer's Aid #1 Installation and Operating Manual
; ==============================================================================
; Analyzed (via McFadden's SourceGen) by James Davis [Last Updated: 2020-07-10]
; ==============================================================================
;
; ==============================================================================
; Relocater Routines 6502 Equates:
; ==============================================================================
;
R1L EQU $02 {addr/1} ;Sweet 16 Register #1, Low
INST EQU $0B {addr/3} ;3-Byte Instuction Field
LENGTH EQU $2F {addr/1} ;Disassembler Instruction Display Length
YSAV EQU $34 {addr/1} ;Y-Reg Safe for Monitor Command Processing
A1L EQU $3C {addr/1} ;Monitor General Purpose A1-Reg, Low
A4L EQU $42 {addr/1} ;Monitor General Purpose A4-Reg, Low
INBUFF EQU $0200 ;Input Buffer (6502 Page 2)
SETUSRADR EQU $D5B0 ;Sets Monitor User Command (Ctrl-Y) Vector
SW16 EQU $F689 ;Sweet 16 Interpreter (Op-Codes follow it)
INSDS2 EQU $F88E ;Monitor Disassembler Entry Point
NXTA4 EQU $FCB4 ;Subroutine to Increment Mon A4 Register
ORG $D4D5
;
; ==============================================================================
; Relocater Routines:
; ==============================================================================
; Set Monitor User Command (Ctrl-Y) Vector to Relocater Routine Location:
; ------------------------------------------------------------------------------
;
; ----------------------------------- ;Setup Mon User Cmd (Ctrl-Y) Location:
D4D5: A9 DC SETRLCYV LDA #<RELOC ;Get Relocater Routine Address, Low
D4D7: A0 D4 LDY #>RELOC ;Get Relocater Routine Address, High
D4D9: 4C B0 D5 JMP SETUSRADR ;Setup Mon User Cmd (Ctrl-Y) Vector
; ==============================================================================
; Monitor User Command (Ctrl-Y) Vector Setup Routine:
; ==============================================================================
; Shared by: Relocater, Tape Verify, & RAM Test Routines;
; Located further below, between the Tape Verify & RAM Test Routines:
; ------------------------------------------------------------------------------
; ORG $D5B0
; ----------------------------------------- ;Setup Mon User Cmd (Ctrl-Y) Vector:
; D5B0: 8D F9 03 SETUSRADR STA USRADR+1 ;Preset User Address, Low
; D5B3: 8C FA 03 STY USRADR+2 ;Preset User Address, High
; D5B6: A9 4C LDA #$4C ;Get JMP OpCode
; D5B8: 8D F8 03 STA USRADR ;Preset to JMP OpCode
; D5BB: 60 RTS ;Return to Caller
; ==============================================================================
;
;
; ==============================================================================
; 6502 Relocation Subroutine [For use via Apple II Monitor (at Star {*} Prompt)]
; ==============================================================================
; 1. Define Blocks: *A4<A1.A2 ^Y (^Y is Ctrl-Y)
; ------------------------------------------------------------------------------
; 2. First Segment: *A4<A1.A2 ^Y (If Code)
; *A4<A1.A2M (If Move)
; ------------------------------------------------------------------------------
; 3. Subsequent Segments: *.A2 ^Y (If Code)
; *.A2M (If Move)
; ==============================================================================
;
D4DC: A4 34 RELOC LDY YSAV ;Get Monitor Command Processing Pointer
D4DE: B9 00 02 LDA INBUFF,Y ;Get Monitor Command from Input Buffer
D4E1: C9 AA CMP #'*' | $80 ;Assure we are at the Monitor Prompt
D4E3: D0 0C BNE RELOC2 ;Branch if Not at the Monitor Prompt
; ;Else, Initialize Relocation Pointers:
D4E5: E6 34 INC YSAV ;Advance Command Processing Pointer
D4E7: A2 07 LDX #7 ;Prepare to Copy 8 Bytes ...
D4E9: B5 3C INIT LDA A1L,X ;From: Monitor General Purpose Registers
D4EB: 95 02 STA R1L,X ;To: Sweet 16 Interpreter (ZP) Registers
D4ED: CA DEX ;Reduce Byte-Count Index-Pointer
D4EE: 10 F9 BPL INIT ;Loop until all Bytes have been Copied
D4F0: 60 RTS ;Then Return to Caller
D4F1: A0 02 RELOC2 LDY #2 ;Prepare to Copy 3 Bytes ...
D4F3: B1 3C GETINS LDA (A1L),Y ;From: A1 Address Pointer [(Indirect),Y]
D4F5: 99 0B 00 STA INST,Y ;To: 3-Byte Instuction Field [Abs,Y]
D4F8: 88 DEY ;Reduce Byte-Count Index-Pointer
D4F9: 10 F8 BPL GETINS ;Loop until all Bytes have been Copied
; ;Compute Instruction Length from Op-Code:
D4FB: 20 8E F8 JSR INSDS2 ;Monitor Disassembler Entry Point
D4FE: A6 2F LDX LENGTH ;Disassembler Instruction Display Length
; ;^[Sets X=# of Bytes: 1, 2, or 3]
D500: CA DEX ;Reduce Byte-Count Index-Pointer
; ;^[Now, # of Bytes is X+1: X= 0, 1, or 2]
D501: D0 0C BNE TRANSLATE ;If Not Zero, Interpret Sweet 16 Op-Codes
D503: A5 0B LDA INST ;Get Instuction from 3-Byte Field
D505: 29 0D AND #%00001101 ;Weed Out Non-Zero-Page ...
D507: F0 14 BEQ STINST ; 2-Byte Immediate Operations
D509: 29 08 AND #%00001000 ;If Zero-Page Address, ...
D50B: D0 10 BNE STINST ; Then Clear High Byte
D50D: 85 0D STA INST+2 ;3-Byte Instuction Field
D50F: 20 89 F6 TRANSLATE JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)...
; ==============================================================================
; *** SourceGen needs a way to interpret Sweet 16 Operations like the following:
; [See: "SWEET16: The 6502 Dream Machine"; BYTE Magazine, Nov 1977, Pgs 150~159]
; [And: "Apple II Reference Manual (Red Book)"; §C6 Sweet 16 Listing, Pgs 96~99]
; ==============================================================================
; Sweet 16 Equates: Zero-Page Locations used here for Sweet 16 Interpreter Op's
; ==============================================================================
; FRMBEG EQU $01 {addr/1} ;SW16/R0H: Beginning of Source Block
; FRMEND EQU $02 {addr/2} ;SW16/R1L: End of Source Block {Low/High}*
; TOBEG EQU $04 {addr/2} ;SW16/R2L: Beginning of Destination Block*
; ADR EQU $06 {addr/2} ;SW16/R3L: Address Part of Instuction
; ==============================================================================
; TRANSLATE JSR SW16 ;Sweet 16 Interpreter (Op-Codes follow)...
; ^ XLATE ^ ------------------------------------- ;If Address of Zero Page
D512: 22 DFB $22 ;LD FRMEND ;or Absolute Address is in
D513: D6 DFB $D6 ;CPR ADR ;Source (FRM) Block then
D514: 02 06 DDB $0206 ;BNC SW16RT ;Substitute:
D516: 26 DFB $26 ;LD ADR ;(Address Part of Instuction)
D517: B1 DFB $B1 ;SUB FRMBEG ;-(Source Start Address)
D518: 02 02 DDB $0202 ;BNC SW16RT ;[Exit: Branch if No Carry]
D51A: A4 DFB $A4 ;ADD TOBEG ;+(Destination Start Address)
D51B: 36 DFB $36 ;ST ADR ;(Address Part of Instuction)
D51C: 00 :SW16RT DFB $00 ;RTN ;[Return to 6502 Mode]
; ==============================================================================
;
D51D: A2 00 STINST LDX #0 ;Clear X-Index; Prep to Copy LENGTH Bytes
D51F: B5 0B STINS2 LDA INST,X ;From: 3-Byte Instuction Field [Abs,X]
D521: 91 42 STA (A4L),Y ;To: A4 Address Pointer [(Indirect),Y]
D523: E8 INX ;Advance X-Index
D524: 20 B4 FC JSR NXTA4 ;Subroutine to Increment Mon A4 Register
D527: C6 2F DEC LENGTH ;Disassembler Instruction Display Length
D529: 10 F4 BPL STINS2 ;Loop until all Bytes have been Copied
D52B: 90 C4 BCC RELOC2 ;Loop until Relocation is Finished
D52D: 60 RTS ;Return to Caller